package com.xxpt.common.utils;

import org.springframework.cglib.beans.BeanCopier;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanCopyUtils {
    /**
     * 创建过的BeanCopier实例放到缓存中，下次可以直接获取，提升性能
     */
    private static final Map<String, BeanCopier> BEAN_COPIERS = new ConcurrentHashMap<>();

    /**
     * 简单进行常规属性拷贝
     *
     * @param srcObj  源对象
     * @param destObj 目标对象
     */
    public static void copy(Object srcObj, Object destObj) {
        String key = genKey(srcObj.getClass(), destObj.getClass());
        BeanCopier copier;
        if (!BEAN_COPIERS.containsKey(key)) {
            copier = BeanCopier.create(srcObj.getClass(), destObj.getClass(), false);
            BEAN_COPIERS.put(key, copier);
        } else {
            copier = BEAN_COPIERS.get(key);
        }
        copier.copy(srcObj, destObj, null);
    }

    /**
     * 简单进行常规属性拷贝
     * @param srcObj  源对象
     */
    public static <T> T copy(Object srcObj, Class<T> clazz) {
        T target;
        try {
            target = clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException();
        }
        copy(srcObj, target);
        return target;
    }

    /**
     * 拷贝 list
     * @param srcList
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> copyList(List<?> srcList, Class<T> clazz) {
        if (CollectionUtils.isEmpty(srcList)) {
            return null;
        }
        List<T> result = new ArrayList<>(srcList.size());
        for (Object source : srcList) {
            T target;
            try {
                target = clazz.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                throw new RuntimeException();
            }
            copy(source, target);
            //BeanUtils.copyProperties(source, target);
            result.add(target);
        }
        return result;
    }

    private static String genKey(Class<?> srcClazz, Class<?> destClazz) {
        return srcClazz.getName() + destClazz.getName();
    }
}
